package kr.ac.kongju.gedl.board.web;

import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;

import kr.ac.kongju.gedl.attach.service.AttachFileService;
import kr.ac.kongju.gedl.attach.vo.AttachFileVO;
import kr.ac.kongju.gedl.board.service.BoardContentsService;
import kr.ac.kongju.gedl.board.vo.BulletinBoardVO;
import kr.ac.kongju.gedl.board.vo.ContentsVO;
import kr.ac.kongju.gedl.cmmn.web.CU;
import kr.ac.kongju.gedl.cmmn.web.NavigationController;
import kr.ac.kongju.gedl.code.vo.CodeInfoVO;
import kr.ac.kongju.gedl.common.util.DateUtil;
import kr.ac.kongju.gedl.common.util.ListResultVO;
import kr.ac.kongju.gedl.common.util.ResultCommand;
import kr.ac.kongju.gedl.item.web.ItemController;

import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.dozer.DozerBeanMapperSingletonWrapper;
import org.dozer.Mapper;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.tags.HtmlEscapeTag;
import org.springframework.web.util.HtmlUtils;

import egovframework.rte.fdl.property.EgovPropertyService;
import egovframework.rte.ptl.mvc.tags.ui.pagination.PaginationInfo;

@Controller
public class AdminBoardContentsController {
	
	/** EgovPropertyService */
    @Resource(name = "propertiesService")
    protected EgovPropertyService propertiesService;
    
    @Resource(name = "reportService")
    protected BoardContentsService boardContentsService;
    
    
    @Resource(name = "attachFileService")
    protected AttachFileService attachFileService;
    
	
    @RequestMapping(value="/admin/contentsForm.do")
	public String contentsWrite(@ModelAttribute("contentsVO") ContentsVO contentsVO,
			@RequestParam(value="viewType", defaultValue="insert") String viewType,
			ModelMap model, SessionStatus status) throws Exception {
		
    	
    	ContentsVO boardContentsVO = new ContentsVO();
		
		if(viewType.equals("update") && contentsVO.getContentsGroupId() > 0){
			List<ContentsVO> contentsGroupList = boardContentsService.retrieveBoardContents(contentsVO);
			if(contentsGroupList != null && contentsGroupList.size() == 1) {
				boardContentsVO = contentsGroupList.get(0);
				AttachFileVO searchCondition = new AttachFileVO();
				searchCondition.setContentsId(boardContentsVO.getContentsGroupId()+"_"+boardContentsVO.getContentsSeq());
				List<AttachFileVO> attachFileList = attachFileService.selectListAttachFile(searchCondition);
				boardContentsVO.setAttachFileList(attachFileList);
			}
		} else if(viewType.equals("reply")) {
			boardContentsVO = contentsVO;
			
		} else {
			boardContentsVO.setBoardId(contentsVO.getBoardId());
		}
		List<CodeInfoVO> regionList1 = CU.getInstance().getCodeList("REGION");

    	String contentsCategoryCd = StringUtils.defaultIfEmpty(contentsVO.getContentsCategoryCd(), "");
    	
    	if(contentsCategoryCd.length() >= 4) {
	    	List<CodeInfoVO> regionList2 = CU.getInstance().getCodeList(contentsCategoryCd.substring(0, 4));
			model.addAttribute("regionList2", regionList2);
    	}
		
    	if(contentsCategoryCd.length() >= 7) {
    		List<CodeInfoVO> regionList3 = CU.getInstance().getCodeList(contentsCategoryCd.substring(0, 7));
    		model.addAttribute("regionList3", regionList3);
    	}
		
		model.addAttribute("regionList", regionList1);
		model.addAttribute("boardInfo", boardContentsService.retrieveBulletinBoard(contentsVO.getBoardId()));
		model.addAttribute("adminContentsVO", boardContentsVO);
    	
		return "/admin/contentsWrite";
	}
    
    
    /**
     * 관리자 게시물 등록
     * @param contentsVO
     * @param model
     * @param status
     * @return
     * @throws Exception
     */
    @RequestMapping(value="/admin/insertContents.do")
	public String adminInsertSave(@ModelAttribute("contentsVO") ContentsVO contentsVO, 
			HttpServletRequest request, ModelMap model, SessionStatus status) throws Exception {
		
    	if(contentsVO.getContentsGroupId() == 0) {
			contentsVO.setContentsGroupId(boardContentsService.getContentsGroupId());
			contentsVO.setContentsSeq(1);
			contentsVO.setContentsDepth(1);
		} else {
			contentsVO.setContentsSeq(boardContentsService.getContentsSeq(contentsVO.getContentsGroupId()));
			contentsVO.setContentsDepth(contentsVO.getContentsDepth()+1);
		}
    	
    	contentsVO.setContentsDesc(HtmlUtils.htmlUnescape(contentsVO.getContentsDesc()));
    	boardContentsService.registerBoardContents(contentsVO);
    	if (request instanceof MultipartHttpServletRequest) {
    		attachFileList(1, contentsVO, request);
		}
		
		status.setComplete();
		
		return "redirect:/board/contentsView.do?boardId="+contentsVO.getBoardId()+"&contentsGroupId="+contentsVO.getContentsGroupId();
    	
	}
    
    /**
     * 관리자 게시물 수정
     * @param contentsVO
     * @param model
     * @param status
     * @return
     * @throws Exception
     */
    @RequestMapping(value="/admin/updateContents.do", method=RequestMethod.POST)
	public String adminUpdateReport(@ModelAttribute("contentsVO") ContentsVO contentsVO, 
			HttpServletRequest request, ModelMap model, SessionStatus status) throws Exception {
		
    	List<AttachFileVO> attachFileList = contentsVO.getAttachFileList();
		ContentsVO boardContentsVO = new ContentsVO();
		
		if(contentsVO.getContentsGroupId() > 0 && contentsVO.getContentsSeq() > 0){
			contentsVO.setContentsDesc(HtmlUtils.htmlUnescape(contentsVO.getContentsDesc()));
			boardContentsVO = boardContentsService.updateBoardContents(contentsVO);
		}
		
		AttachFileVO searchCondition = new AttachFileVO();
		searchCondition.setContentsId(boardContentsVO.getContentsGroupId()+"_"+boardContentsVO.getContentsSeq());
		List<AttachFileVO> oldAttachFileList = attachFileService.selectListAttachFile(searchCondition);
		
		/**
		 * 기존 첨부파일목록과 화면에서 전달받은 첨부파일 목록을 비교하여 화면에서 받은 목록에
		 * 존재하지 않는 파일들은 삭제 처리 한다.
		 */
		for(AttachFileVO oldAttachFile : oldAttachFileList) {
			boolean isExist = false;
			for(AttachFileVO attachFile : attachFileList) {
				if(oldAttachFile.getAttachFileSeq() == attachFile.getAttachFileSeq()) {
					isExist = true;
				}
			}
			if(!isExist) {
				attachFileService.deleteAttachFile(oldAttachFile);
			}
		}
		// 첨부파일의 시퀀스는 기존 첨부파일 목록의 맨 마지막 시퀀스에 +1
		int attachFileSeq = 0;
		if(attachFileList != null && attachFileList.size() > 0) {
			attachFileSeq = attachFileList.get(attachFileList.size()-1).getAttachFileSeq() + 1;
		}
		if (request instanceof MultipartHttpServletRequest) {
    		attachFileList(attachFileSeq, contentsVO, request);
		}
		
		
		
		status.setComplete();
		
		return "redirect:/board/contentsView.do?boardId="+contentsVO.getBoardId()+"&contentsGroupId="+contentsVO.getContentsGroupId();
	}
    
    /**
     * 관리자 게시물 삭제
     * @param contentsVO
     * @param model
     * @param status
     * @return
     * @throws Exception
     */
    @RequestMapping(value="/admin/deleteContents.do", method=RequestMethod.POST)
	public ModelAndView adminDeleteReport(@ModelAttribute("contentsVO") ContentsVO contentsVO, 
    		ModelMap model, SessionStatus status) throws Exception {
		
		ModelAndView modelAndView = new ModelAndView("jsonView");
		
		if(contentsVO.getContentsGroupId() > 0){	//등록
			int result = boardContentsService.deleteBoardContents(contentsVO);
			if(result > 0){
				modelAndView.addObject(ResultCommand.RESULT, "true");
	            modelAndView.addObject(ResultCommand.MESSAGE, "삭제되었습니다.");
	            
	            //첨부파일 정보를 삭제한다
	            //int deleteRowCount = attachFileMgr.deleteListAttachFile("NOTICE", boardContents.getBoardContentsId());
	            //logger.info("[DELETE] targetId:{} attachFile count:{}", boardContents.getBoardContentsId(), deleteRowCount);
	            
	            //기존 첨부파일 사용안함으로 플래그 처리
				AttachFileVO attachFile = new AttachFileVO();
				attachFile.setContentsId(contentsVO.getContentsGroupId()+"_"+contentsVO.getContentsSeq());
				attachFileService.deleteListAttachFile(attachFile);
				
				//logger.info("[DEBUG] updateListAttachFile result:{}", updateResult);
			}else{
				modelAndView.addObject(ResultCommand.RESULT, "false");
	            modelAndView.addObject(ResultCommand.MESSAGE, "삭제시 오류가 발생하였습니다");
			}
		}else{											//갱신
			modelAndView.addObject(ResultCommand.RESULT, "false");
            modelAndView.addObject(ResultCommand.MESSAGE, "삭제시 오류가 발생하였습니다");
		}
		
		status.setComplete();
		
		return modelAndView;
	}
    
    public void attachFileList(int attachFileSeq, ContentsVO contentsVO, HttpServletRequest request) throws Exception{
    	List<AttachFileVO> attachFileList = new ArrayList<AttachFileVO>();
			
			// 파일 저장 경로
			String filePath = propertiesService.getString("attach.file.path")+File.separatorChar+DateFormatUtils.format(Calendar.getInstance(), "yyyyMMdd")+File.separatorChar;
			String thumbnailFilePath = propertiesService.getString("thumbnail.file.path")+File.separatorChar+DateFormatUtils.format(Calendar.getInstance(), "yyyyMMdd")+File.separatorChar;
			File attachDir = new File(filePath);
			if(!attachDir.exists()) {
				attachDir.mkdirs();
			}
			
			File thumbnailDir = new File(thumbnailFilePath);
			if(!thumbnailDir.exists()) {
				thumbnailDir.mkdirs();
			}
			
			String contentsId = contentsVO.getContentsGroupId()+"_"+contentsVO.getContentsSeq();
			
			
			// 첨부파일 저장
			MultipartFile attachfile = ((MultipartHttpServletRequest)request).getFile("attachFile");
			if(!attachfile.isEmpty()) {
				attachFileList.add(processAttachFile(attachfile, filePath, contentsId, attachFileSeq, NavigationController.TYPE_ATTACH_FILE, "첨부파일"));
			}
			
			// 대표이미지 저장
			attachFileSeq = 2;
			attachfile = ((MultipartHttpServletRequest)request).getFile("titleImg");
			if(!attachfile.isEmpty()) {
				AttachFileVO attachFileVO = processAttachFile(attachfile, filePath, contentsId, attachFileSeq, NavigationController.TYPE_THUMBNAIL, "썸네일");
				attachFileVO = makeThumbnailFile(attachfile, attachFileVO, thumbnailFilePath, 270, 195);
				attachFileList.add(attachFileVO);
			}
			
			// 주제도 파일 저장
			List<MultipartFile> themeMapList = ((MultipartHttpServletRequest)request).getFiles("themeMap");
			String[] themeMapTitles = request.getParameterValues("themeMapTitle");
			if(themeMapList != null && themeMapList.size() > 0) {
				int idx = 0;
				for(MultipartFile themeMapFile : themeMapList) {
					if(!themeMapFile.isEmpty()) {
						attachFileSeq++;
						AttachFileVO attachFileVO = processAttachFile(themeMapFile, filePath, contentsId, attachFileSeq, NavigationController.TYPE_IMAGE, themeMapTitles[idx]);
						attachFileVO = makeThumbnailFile(themeMapFile, attachFileVO, thumbnailFilePath, 676, 610);
						attachFileList.add(attachFileVO);
						
						idx++;
					}
				}
			}
			
			if(attachFileList.size() > 0) {
				contentsVO.setAttachFileList(attachFileList);
			}
						
			attachFileService.registerAttachFileList(attachFileList);
    }
    
    public static AttachFileVO processAttachFile(MultipartFile attachfile, String filePath, String contentsId, int attachFileSeq, String attachType, String fileDesc) throws Exception{
    	AttachFileVO attachFileVO = null;
    	String oName = attachfile.getOriginalFilename();
		String format = oName.substring(oName.lastIndexOf("."), oName.length());
		String newFileName = System.currentTimeMillis()+format;
		attachFileVO = new AttachFileVO();
		attachFileVO.setContentsId(contentsId);
		attachFileVO.setAttachFileSeq(attachFileSeq);
		attachFileVO.setAttachFileTypeCd(attachType);
		attachFileVO.setAttachFileNm(newFileName);
		attachFileVO.setAttachFileOriginNm(attachfile.getOriginalFilename());
		attachFileVO.setAttachFilePath(filePath+attachFileVO.getAttachFileNm());
		attachFileVO.setAttachFileDesc(fileDesc);
		FileOutputStream fos = new FileOutputStream(new File(attachFileVO.getAttachFilePath()));
		FileCopyUtils.copy(attachfile.getInputStream(), fos);
		fos.close();
		
		return attachFileVO;
    }
    
    public static AttachFileVO makeThumbnailFile(MultipartFile attachfile, AttachFileVO attachFileVO, String filePath, int width, int height) throws Exception{
    	
		attachFileVO.setThumbnailImgPath(filePath+attachFileVO.getAttachFileNm());
		
		BufferedImage originalImage = ImageIO.read(attachfile.getInputStream());
		int type = originalImage.getType() == 0? BufferedImage.TYPE_INT_ARGB : originalImage.getType();
 
		BufferedImage resizeImageJpg = resizeImageWithHint(originalImage, type, width, height);
		ImageIO.write(resizeImageJpg, "jpg", new File(attachFileVO.getThumbnailImgPath())); 
		
		return attachFileVO;
    }
    
    private static BufferedImage resizeImageWithHint(BufferedImage originalImage, int type, int width, int height){
    	 
    	BufferedImage resizedImage = new BufferedImage(width, height, type);
    	Graphics2D g = resizedImage.createGraphics();
    	g.drawImage(originalImage, 0, 0, width, height, null);
    	g.dispose();	
    	g.setComposite(AlphaComposite.Src);
     
    	g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
    	RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    	g.setRenderingHint(RenderingHints.KEY_RENDERING,
    	RenderingHints.VALUE_RENDER_QUALITY);
    	g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
    	RenderingHints.VALUE_ANTIALIAS_ON);
     
    	return resizedImage;
    }	
	
	
}
